package hos.thread;

import android.util.Log;

import hos.thread.executor.TS;

/**
 * <p>Title: RunnableJob </p>
 * <p>Description:  </p>
 * <p>Company: www.mapuni.com </p>
 *
 * @author : 蔡俊峰
 * @version : 1.0
 * @date : 2023/8/10 9:15
 */
@SuppressWarnings("unchecked")
public class RunnableJob<T> extends RunnableLife {

    public static <T> RunnableJob<T> run(ThreadOption.onBackgroundListener<T> onBackground) {
        return new RunnableJob<>(onBackground).start(ThreadOption.Job.ON);
    }

    public static <T> RunnableJob<T> run(ThreadOption.onBackgroundListener<T> onBackground, ThreadOption.Job job) {
        return new RunnableJob<>(onBackground).start(job);
    }

    public static <T> RunnableJob<T> get(ThreadOption.onBackgroundListener<T> onBackground) {
        return new RunnableJob<>(onBackground);
    }

    private final ThreadOption.onBackgroundListener<T> onBackground;

    protected RunnableJob(ThreadOption.onBackgroundListener<T> onBackground) {
        this.onBackground = onBackground;
    }

    public RunnableJob<T> start() {
        return start(ThreadOption.Job.ON);
    }

    public RunnableJob<T> start(ThreadOption.Job job) {
        if (isRunning()) {
            return this;
        }
        reset();
        if (job == ThreadOption.Job.TO) {
            TS.postIo(this);
            return this;
        }
        TS.postOnIo(this);
        return this;
    }

    protected ThreadOption.onSuccessListener<T> onSuccess = null;

    public RunnableJob<T> onSuccess(ThreadOption.onSuccessListener<T> success) {
        this.onSuccess = success;
        return this;
    }

    /**
     * 结果处理
     */
    protected void postResult(T result) {
        runUI(() -> {
            try {
                // 执行完成
                Log.d("Thread", "onSuccess");
                if (onSuccess != null) {
                    onSuccess.onSuccess(this, result);
                }
                changedStatus(ThreadOption.Status.ON_SUCCESS);
            } catch (Throwable e) {
                // 异常
                postThrowable(e);
            }
        });
    }

    @Override
    public void progressUpdate(Double value) {
        postProgress(value);
    }

    @Override
    public RunnableJob<T> setStatusListener(ThreadOption.onStatusChangedListener listener) {
        return (RunnableJob<T>) super.setStatusListener(listener);
    }

    @Override
    public RunnableJob<T> onStart(ThreadOption.onStartListener start) {
        return (RunnableJob<T>) super.onStart(start);
    }

    @Override
    public RunnableJob<T> onProgress(ThreadOption.onProgressListener progress) {
        return (RunnableJob<T>) super.onProgress(progress);
    }

    @Override
    public RunnableJob<T> onCatch(ThreadOption.onThrowableListener throwable) {
        return (RunnableJob<T>) super.onCatch(throwable);
    }

    @Override
    public RunnableJob<T> onCancel(ThreadOption.onCancelListener onCancel) {
        return (RunnableJob<T>) super.onCancel(onCancel);
    }

    @Override
    public void run(RunnableThis run) {
        Thread currentThread = Thread.currentThread();
        try {
            currentThread.setUncaughtExceptionHandler((t, e) -> postThrowable(e));
            if (isCancel()) {
                // 取消
                postCancel();
                return;
            }
            postStart();
            // 运行
            T result = runBackground();
            if (isCancel() && isStatus(ThreadOption.Status.ON_DESTROY)) {
                // 已经取消，并且被销毁了，说明当前页面
                Log.d("Thread", "onCancel && onDestroy");
                return;
            }
            Log.d("Thread", "onBackgroundSuccess");
            if (isCancel()) {
                // 取消
                postCancel();
                return;
            }
            postResult(result);
        } catch (Throwable e) {
            postThrowable(e);
        } finally {
            //移除所有消息.防止需要执行onCompleted了，onPrepare还没被执行，那就不需要执行了
//            MH.getHandler().removeCallbacksAndMessages(null);
            changedStatus(ThreadOption.Status.ON_DESTROY);
        }
    }

    protected T runBackground() throws Throwable {
        Log.d("Thread", "onBackground");
        changedStatus(ThreadOption.Status.ON_RUNNING);
        return onBackground.onBackground(this);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        onSuccess = null;
    }
}
